2.5 配置中心

Spring Cloud Config提供了一种在分布式系统中外部化配置服务器和客户端的支持。配置服务器有一个中心位置,管理所有环境下的应用的外部属性。客户端和服务器映射到相同Spring Eventment 和 PropertySrouce抽象的概念,所以非常适合Spring应用,但也可以在任何语言开发的任何应用中使用。在一个应用从开发、测试到生产的过程中,你可以分别地管理开发、测试、生产环境的配置,并且在迁移的时候获取相应的配置来运行。

Config Server 存储后端默认使用git存储配置信息,因此可以很容易支持标记配置环境的版本,同时可以使用一个使用广泛的工具管理配置内容。当然添加其他方式的存储实现也是很容易的。

参考:

http://cloud.spring.io/spring-cloud-static/Brixton.SR5/#_spring_cloud_config

核心代码:

org.springframework.cloud.config.server.environment.NativeEnvironmentRepository,留意其中的findOne方法。

代码示例

准备工作

  • 为了更贴近生产,我们首先配置Host
  1. 127.0.0.1 config-server
  1. microservice-config-client-dev.properties
  2. microservice-config-client.properties

其中在:microservice-config-client-dev.properties 文件中添加如下内容:

  1. profile=dev

服务器端代码示例

创建一个Maven项目,在pom.xml文件中添加如下内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <artifactId>microservice-config-server</artifactId>
  6. <packaging>jar</packaging>
  7. <parent>
  8. <groupId>com.itmuch.cloud</groupId>
  9. <artifactId>spring-cloud-microservice-study</artifactId>
  10. <version>0.0.1-SNAPSHOT</version>
  11. </parent>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-config-server</artifactId>
  16. </dependency>
  17. </dependencies>
  18. </project>

启动类:

  1. /**
  2. * 通过@EnableConfigServer注解激活配置服务.
  3. * 说明:
  4. * 在application.yml中有个git.uri的配置,目前配置的是https://github.com/eacdy/spring-cloud-study/
  5. * 获取git上的资源信息遵循如下规则:
  6. * /{application}/{profile}[/{label}]
  7. * /{application}-{profile}.yml
  8. * /{label}/{application}-{profile}.yml
  9. * /{application}-{profile}.properties
  10. * /{label}/{application}-{profile}.properties
  11. *
  12. * 例如本例:可使用以下路径来访问microservice-config-client-dev.properties:
  13. * http://localhost:8040/microservice-config-client-dev.properties
  14. * http://localhost:8040/microservice-config-client/dev
  15. * ...
  16. * @author eacdy
  17. */
  18. @SpringBootApplication
  19. @EnableConfigServer
  20. public class ConfigServerApplication {
  21. public static void main(String[] args) {
  22. SpringApplication.run(ConfigServerApplication.class, args);
  23. }
  24. }

配置文件:application.yml

  1. server:
  2. port: 8040
  3. spring:
  4. application:
  5. name: microservice-config-server
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: https://github.com/eacdy/spring-cloud-study/ # 配置git仓库的地址
  11. search-paths: config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
  12. username: # git仓库的账号
  13. password: # git仓库的密码

这样,一个Config Server就完成了。

测试工作

获取git上的资源信息遵循如下规则
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

例如本例:可使用以下路径来访问microservice-config-client-dev.properties
http://localhost:8040/microservice-config-client-dev.properties
http://localhost:8040/microservice-config-client/dev

按照上文,我们成功搭建了Config Server,并测试能够正常获取到git仓库中的配置信息。那么对于一个微服务应用,如何才能获取配置信息呢?

配置服务客户端示例

新建一个Maven项目,在pom.xml中添加如下内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <artifactId>microservice-config-client</artifactId>
  6. <packaging>jar</packaging>
  7. <parent>
  8. <groupId>com.itmuch.cloud</groupId>
  9. <artifactId>spring-cloud-microservice-study</artifactId>
  10. <version>0.0.1-SNAPSHOT</version>
  11. </parent>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-config</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-actuator</artifactId>
  24. </dependency>
  25. </dependencies>
  26. </project>

编写启动类:

  1. @SpringBootApplication
  2. public class ConfigClientApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(ConfigClientApplication.class, args);
  5. }
  6. }

编写测试Controller

  1. /**
  2. * 这边的@RefreshScope注解不能少,否则即使调用/refresh,配置也不会刷新
  3. * @author eacdy
  4. */
  5. @RestController
  6. @RefreshScope
  7. public class ConfigClientController {
  8. @Value("${profile}")
  9. private String profile;
  10. @GetMapping("/hello")
  11. public String hello() {
  12. return this.profile;
  13. }
  14. }

配置文件:application.yml

  1. server:
  2. port: 8041

配置文件bootstrap.yml(为什么要使用bootstrap.yml而不直接放在application.yml中的原因见注意点

  1. spring:
  2. application:
  3. name: microservice-config-client # 对应microservice-config-server所获取的配置文件的{application}
  4. cloud:
  5. config:
  6. uri: http://config-server:8040/
  7. profile: dev # 指定profile,对应microservice-config-server所获取的配置文件中的{profile}
  8. label: master # 指定git仓库的分支,对应microservice-config-server所获取的配置文件的{label}

启动,并访问:

http://localhost:8041/hello ,我们会发现此时可以显示git仓库中配置文件的内容:

  1. dev

配置内容的热加载

如果不重启应用,能够做到配置的刷新吗?答案显然是可以的。

我们将microservice-config-client-dev.properties中值改为

  1. profile=abcd

并提交到git仓库。

然后使用命令(本文使用的是curl,Linux和Windows都有curl工具,当然也可以借助其他工具,例如Postman等):

  1. curl -X POST http://localhost:8041/refresh

然后再次访问http://localhost:8041/hello ,将会看到:abcd ,说明配置已经刷新。

配置服务与注册中心联合使用

在生产环境中,我们可能会将Config Server 与 Eureka等注册中心联合使用(注意:目前Spring Cloud只支持与Eureka及Consul联合使用,不支持与Zookeeper联合使用),下面讲解如何将Config Server与 Eureka 联合使用。

准备工作

  1. 启动服务microservice-discovery-eureka
  2. 和上文一样,准备好几个配置文件,命名规范为项目名称-环境名称.properties ,本文使用的名称是microservice-config-client-eureka-dev.properties

代码示例

服务器端代码示例:

首先新建一个Maven项目,在pom.xml 中添加如下内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <artifactId>microservice-config-server-eureka</artifactId>
  6. <packaging>jar</packaging>
  7. <parent>
  8. <groupId>com.itmuch.cloud</groupId>
  9. <artifactId>spring-cloud-microservice-study</artifactId>
  10. <version>0.0.1-SNAPSHOT</version>
  11. </parent>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-config-server</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-eureka</artifactId>
  20. </dependency>
  21. </dependencies>
  22. </project>

启动类:ConfigServerEurekaApplication.java

  1. @SpringBootApplication
  2. @EnableConfigServer
  3. @EnableDiscoveryClient
  4. public class ConfigServerEurekaApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(ConfigServerEurekaApplication.class, args);
  7. }
  8. }

配置文件:application.yml

  1. server:
  2. port: 8050
  3. spring:
  4. application:
  5. name: microservice-config-server-eureka
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: https://github.com/eacdy/spring-cloud-study/
  11. search-paths: config-repo
  12. username:
  13. password:
  14. eureka:
  15. client:
  16. serviceUrl:
  17. defaultZone: http://discovery:8761/eureka/

客户端示例

创建一个Maven项目,在pom.xml 中添加如下内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <artifactId>microservice-config-client-eureka</artifactId>
  6. <packaging>jar</packaging>
  7. <parent>
  8. <groupId>com.itmuch.cloud</groupId>
  9. <artifactId>spring-cloud-microservice-study</artifactId>
  10. <version>0.0.1-SNAPSHOT</version>
  11. </parent>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-config</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.cloud</groupId>
  23. <artifactId>spring-cloud-starter-eureka</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-actuator</artifactId>
  28. </dependency>
  29. </dependencies>
  30. </project>

启动类:ConfigClientEurekaApplication.java

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. public class ConfigClientEurekaApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(ConfigClientEurekaApplication.class, args);
  6. }
  7. }

编写测试Controller

  1. /**
  2. * 这边的@RefreshScope注解不能少,否则即使调用/refresh,配置也不会刷新
  3. * @author eacdy
  4. */
  5. @RestController
  6. @RefreshScope
  7. public class ConfigClientController {
  8. @Value("${profile}")
  9. private String profile;
  10. @GetMapping("/hello")
  11. public String hello() {
  12. return this.profile;
  13. }
  14. }

配置文件:application.yml

  1. server:
  2. port: 8051

配置文件:bootstrap.yml

  1. spring:
  2. application:
  3. name: microservice-config-client-eureka
  4. cloud:
  5. config:
  6. profile: dev
  7. label: master
  8. discovery:
  9. enabled: true # 默认false,设为true表示使用注册中心中的configserver配置而不自己配置configserver的uri
  10. serviceId: microservice-config-server-eureka # 指定config server在服务发现中的serviceId,默认为:configserver
  11. eureka:
  12. client:
  13. serviceUrl:
  14. defaultZone: http://discovery:8761/eureka/
  15. # 参考文档:https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#discovery-first-bootstrap

从示例代码我们发现,想要将Config Server 与 注册中心联合使用,只需要在客户端侧配置spring.cloud.config.discovery.enabled=truespring.cloud.config.discovery.serviceId 两个配置项即可。Eureka的配置前文有讲到过,如有疑问,详见服务发现的相关章节。

注意:当服务发现是EurekaConsul 时,Config Server支持与之联合使用;如果是Zookeeper 做服务发现,目前不支持与之联合使用。

注意点:

  • client需要添加以下依赖,否则访问/refresh将会得到404:
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>
  • client的controller需要添加@RefreshScope注解,否则配置无法刷新。
  • 本文的bootstrap.yml文件中的内容不能放到application.yml中,否则config部分无法被加载,因为config部分的配置先于application.yml被加载,而bootstrap.yml中的配置会先于application.yml加载,
  • Config Server也可以支持本地存储或svn而不使用git,相对较为简单,故而本文不作赘述,有兴趣的可以自行阅读Spring Cloud的文档。

参考文档:

Config Server与注册中心联合使用:https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#discovery-first-bootstrap

Config Server的高可用: https://github.com/spring-cloud/spring-cloud-config/issues/87